iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 29
1
Software Development

Laravel 原始碼分析系列 第 29

分析 Auth(6)--Authorization

  • 分享至 

  • xImage
  •  

Laravel 文件有提到幾種方法來確認授權:

  • Via The User Model
  • Via Middleware
  • Via Controller Helpers
  • Via Blade Templates

不討論 Blade Templates 的部分,因為這會牽扯到 View,太複雜了。

以下先假設有這樣的設定:

Gate::define('update-post', function ($user, $post) {
    return $user->id == $post->user_id;
});

官方提供的範例都會有兩種:正常狀況與不需指定 Model 的操作(Actions That Don't Require Models),但分析起來其實沒什麼太大差異。

User Model

官方提供的範例如下:

use App\Post;

if ($user->can('update', $post)) {
}

if ($user->can('create', Post::class)) {
}

來看 can() 的原始碼,它寫在 Illuminate\Foundation\Auth\Access\Authorizable

public function can($ability, $arguments = [])
{
    return app(Gate::class)->forUser($this)->check($ability, $arguments);
}

寫得非常的好理解,它透過 forUser() 來把自己代入,接著再呼叫 check() 檢查。

Authorize Middleware

官方提供的範例如下:

use App\Post;

Route::put('/post/{post}', function (Post $post) {

})->middleware('can:update,post');

Route::post('/post', function () {

})->middleware('can:create,App\Post');

與驗證類似,授權也有專用的 Middleware,就叫 Authorize。它的 handle() 實作如下:

public function handle($request, Closure $next, $ability, ...$models)
{
    $this->gate->authorize($ability, $this->getGateArguments($request, $models));

    return $next($request);
}

getGateArguments() 會將 $models 參數做 normalize,這部分就不看了。這裡很直接,就呼叫 authorize() 而已。

public function authorize($ability, $arguments = [])
{
    // 取得執行 policy 後的結果
    $result = $this->raw($ability, $arguments);

    // 如果是 Access Response instance 就直接回傳 
    if ($result instanceof Response) {
        return $result;
    }

    // 不是的話,預期會是 true / false ,分別對應到 allow() 與 deny() 方法
    return $result ? $this->allow() : $this->deny();
}

這裡跟 check() 有點類似,不過差別在它回傳的固定會是 Response。如果是 bool 的話,則會使用 allow()deny() 轉換成 Response 或 Exception:

protected function allow($message = null)
{
    return new Response($message);
}

protected function deny($message = 'This action is unauthorized.')
{
    throw new AuthorizationException($message);
}

Controller Helpers

官方提供的範例如下:

use App\Post;

class PostController extends Controller
{
    use AuthorizesRequests;

    public function update(Request $request, Post $post)
    {
        $this->authorize('update', $post);
    }
    
    public function create(Request $request)
    {
        $this->authorize('create', Post::class);
    }
}

authorize() 方法寫在 Illuminate\Foundation\Auth\Access\AuthorizesRequests 裡面

public function authorize($ability, $arguments = [])
{
    list($ability, $arguments) = $this->parseAbilityAndArguments($ability, $arguments);

    return app(Gate::class)->authorize($ability, $arguments);
}

與 middleware 類似的,它也會先解析 ability 與 arguments ,才傳入 Gate 的 authorize() 方法。

到此,Authorization 的分析差不多就結束了,相信大家對於授權會有更進一步的了解。


上一篇
分析 Auth(5)--Authorization
下一篇
總結
系列文
Laravel 原始碼分析46
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言